<?php

/*
 * Copyright (C) 2009 - 2011 Pham Cong Dinh
 *
 * This file is part of Spica.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
// namespace spica\core\utils

/**
 * <p>Set of methods to support string manipulation.</p>
 *
 * @category   spica
 * @package    core
 * @subpackage utils
 * @author     Pham Cong Dinh <pcdinh at phpvietnam dot net>
 * @since      Version 0.3
 * @since      May 03, 2009
 * @copyright  Pham Cong Dinh (http://www.phpvietnam.net)
 * @license    http://www.gnu.org/licenses/lgpl-3.0.txt
 * @version    $Id: StringUtils.php 1869 2011-01-07 18:55:25Z pcdinh $
 */
class SpicaStringUtils
{
    /**
     * Tests if the string it is evaluated for contains a given string.
     *
     * @param  string $string The string to search in
     * @param  string $substring The substring to check
     * @param  bool $caseSensitive The search will be case sensitive
     * @return bool
     */
    public function contains($string, $substring, $caseSensitive = true)
    {
        if (true === $caseSensitive)
        {
            return (false !== strpos($string, $substring));
        }

        return (false !== stripos($string, $substring));
    }

    /**
     * Tests if a string $string ends with a substring $suffix.
     *
     * @param  string $string The string to check
     * @param  string $suffix The substring to check
     * @return bool
     */
    public static function endsWith($string, $suffix)
    {
        return substr($string, 0 - strlen($suffix)) === $suffix;
    }

    /**
     * Tests if a string $string starts with a substring $prefix.
     *
     * @param  string $string The string to check
     * @param  string $prefix The substring to check
     * @return bool
     */
    public static function startsWith($string, $prefix)
    {
        return strpos($string, $prefix) === 0;
    }

    /**
     * Creates a new string which is the result of transforming an underscored
     * or dashed string to camelCase.
     *
     * E.x: 'foo_bar' or 'foo-bar' will be transformed to 'FooBar'.
     *
     * @param  string $string the underscored or dashed words
     * @return string the dashed or underscored string converted to UpperCamelCase
     */
    public static function camelCase($string)
    {
        return str_replace(' ', '', ucwords(str_replace(array('-', '_'), ' ', $string)));
    }

    /**
     * Creates a new string which is the result of transforming an underscored
     * or dashed string to camelCase with the lowercase first letter.
     *
     * @param  string $string the underscored or dashed string
     * @return string the dashed or underscored string converted to lowerCamelCase
     */
    public static function lowerCamelCase($string)
    {
        $str = self::camelCase($string);
        $str[0] = strtolower($string[0]);
        return $string;
    }

    /**
     * Creates a new string which is the result of transforming a camelCase string
     * to a underscore_string.
     *
     * E.x: 'FooBarYeah' is transformed to 'foo_bar'.
     *
     * @param  string $string the camelCased string to convert
     * @return string the CamelCased string converted to an_underscore_string
     */
    public static function underscore($string)
    {
        return strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $string));
    }

    /**
     * Creates a new string which is the result of transforming a camelCase string
     * to a-dashed-string.
     *
     * E.x: 'FooBarYeah' is transformed to 'foo-bar'.
     *
     * @param  string $string the camelCased string to convert
     * @return string the CamelCased string converted to a-dashed-string
     */
    public static function dash($string)
    {
        return strtolower(preg_replace('/(?<=\\w)([A-Z])/', '-\\1', $string));
    }

    /**
     * Replaces the first occurrence of a substring with a new one.
     *
     * @param string $needle Sub-string to find
     * @param string $replace Sub string to replace
     * @param string $haystack Original string
     * @return string
     */
    public static function replaceOnce($needle, $replace, $haystack)
    {
        // Looks for the first occurence of $needle in $haystack and replaces it with $replace.
        $pos = strpos($haystack, $needle);

        if ($pos === false) // Nothing found
        {
            return $haystack;
        }

        return substr_replace($haystack, $replace, $pos, strlen($needle));
    }

    /**
     * Inserts a string fragment into a string.
     *
     * @param  string $string Original string
     * @param  int $offset the offset of the original string that new string will be inserted into
     * @param  string $textToInsert String fragment
     * @return string
     */
    public static function insertAt($string, $offset, $textToInsert)
    {
        return substr($string, 0, $offset) . $textToInsert . substr($string, $offset);
    }

    /**
     * Inserts a substring before first instance of a substring of a string.
     * 
     * @param string $string
     * @param string $beforeThis
     * @param string $textToInsert
     */
    public static function insertBefore($string, $beforeThis, $textToInsert)
    {
        $offset = strpos($string, $beforeThis);

        if (false === $offset)
        {
            return false;
        }

        return substr($string, 0, $offset) . $textToInsert . substr($string, $offset);
    }

    /**
     * Inserts a substring after first instance of a substring of a string.
     *
     * @param string $string
     * @param string $afterThis
     * @param string $textToInsert
     * @return false|string
     */
    public static function insertAfter($string, $afterThis, $textToInsert)
    {
        $offset = strpos($string, $afterThis) + strlen($afterThis);

        if (false === $offset)
        {
            return false;
        }
        
        return substr($string, 0, $offset) . $textToInsert . substr($string, $offset);
    }

    /**
     * Unserializes UTF-8 string.
     *
     * Useful if you put a serialized string in an HTML form on a UTF-8 page.
     *
     * @author seanmurphy Source code is in public domain
     * @param  string $string
     * @return string
     */
    public static function unserialize($string)
    {
        $string = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $string);
        return unserialize($string);
    }

    /**
     * Trims a string from whitespaces, null and control characters.
     *
     * @param  string $string
     * @return string
     */
    public static function trim($string)
    {
        return trim($string, " \x00..\x1F");
    }

    /**
     * Creates a lower case version of a UTF-8 string.
     *
     * @param  string $string
     * @return string
     */
    public static function lc($string)
    {
        return mb_convert_case($string, MB_CASE_LOWER, "UTF-8");
    }

    /**
     * Creates a upper case version of a UTF-8 string.
     *
     * @param  string $string
     * @return string
     */
    public static function uc($string)
    {
        return mb_convert_case($string, MB_CASE_UPPER, "UTF-8");
    }

    /**
     * Converts hex code to binary string. Native bin2hex() converts a string to a hex code and this method
     * is designed to convert it back to original string.
     *
     * @see    http://bugs.php.net/bug.php?id=7829
     * @see    PHP native's bin2hex()
     * @param  string $string
     * @return string
     */
    public static function hex2bin($string)
    {
        return pack("H*", $string); // can be pack("H".$length, $string)
    }

    /**
     * Creates a random string.
     *
     * @param  int  $length   The expected length of string
     * @param  bool $alphanum if true, the result string contains alphanumeric characters only
     * @return string
     */
    public static function rand($length, $alphanum = false)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
        if (false === $alphanum)
        {
            $chars .= '~!@#$%^&*()_+=/?{}[]';
        }

        $count = strlen($chars);
        for ($rand = ''; $length > 0; $length--);
        {
            $rand .= $chars[mt_rand(0, $count - 1)];
        }

        return $rand;
    }

    /**
     * Converts UTF8 string to relevant string to safely add to send mail headers.
     *
     * @see    spica\core\service\NativeMailService
     * @param  string $text
     * @return string
     */
    public static function encodeUtf8MailHeader($text)
    {
        return "=?UTF-8?B?" . base64_encode($text) . "?=";
    }

    /**
     * Converts a normal string to a hexadecimal formatted string which consists of digits and letters from A to F.
     *
     * @see   #hex2bin() for more efficient implementation
     * @param string $string
     * @return string
     */
    public static function stringToHex($string)
    {
        $hex = '';
        
        for ($i = 0, $len = strlen($string); $i < $len; $i++)
        {
            $hex .= dechex(ord($string[$i]));
        }
        
        return $hex;
    }

    /**
     * Converts a hexadecimal formatted string to a normal string.
     *
     * @see    Native bin2hex() for more efficient implementation
     * @see    #stringToHex()
     * @param  string $hex
     * @return string
     */
    public static function hexToString($hex)
    {
        $string = '';

        for ($i = 0, $max = strlen($hex) - 1; $i < $max; $i += 2)
        {
            $string .= chr(hexdec($hex[$i] . $hex[$i + 1]));
        }

        return $string;
    }
}

?>